package com.ifyyf.test.rw;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author if
 * @Description: 读写锁：主要防止多个线程同时写与同时读写导致幻读
 * 读锁：共享锁
 * 写锁：独占锁
 * @Date 2021-11-06 上午 12:31
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) throws InterruptedException {
        MyCache myCache=new MyCache();

        //10个线程只做写入
        for(int i=1;i<=10;i++){
            final int temp=i;
            new Thread(()->{
                myCache.put(temp+"",temp);
            },"write"+i).start();
        }


        //10个线程只做读取
        for(int i=1;i<=10;i++){
            int temp=i;
            new Thread(()->{
                myCache.get(temp + "");
            },"read"+i).start();
        }

    }

    //自定义缓存
    static class MyCache{
        private volatile Map<String,Object> map=new HashMap<>();
        //读写锁，可以通过writeLock和readLock获取写锁和读锁后，再进行上锁
        private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();

        //写的时候，希望只能有一个线程操作
        public void put(String key,Object value){
            //从读写锁readWriteLock中获取写锁writeLock
            Lock writeLock = readWriteLock.writeLock();
            //写锁进行上锁操作
            writeLock.lock();
            try{
                System.out.println(Thread.currentThread().getName()+"写入key = "+key);
                map.put(key,value);
                System.out.println(Thread.currentThread().getName()+"写入完毕");
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                //写锁进行解锁操作
                writeLock.unlock();
            }

        }

        //读的时候，希望每个线程都可以读
        public void get(String key){
            Lock readLock = readWriteLock.readLock();
            readLock.lock();
            try{
                System.out.println(Thread.currentThread().getName()+"读取key = "+key+",value = "+map.get(key));
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                readLock.unlock();
            }
        }
    }
}
